package com.lm;

import com.os.OSAttribute;
import com.os.ObjectSprite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.JPanel;
import mapgenerator.Main;

/**
 *
 * @author Sajarwo Anggai
 */
public class GridWorkspace extends JPanel implements Runnable {

    private Main comp;
    private int tileW, tileH;
    private int pttX, pttY, pttW, pttH;
    private BufferedImage bim;
    private BufferedImage gridWorkspace;
    private BufferedImage layers;
    private BufferedImage layerSprite;
    private Color color;
    private Thread t;
    private boolean draw = false;

    public GridWorkspace(Main comp) {
        this.comp = comp;
        color = new Color(0, 0, 0, 0);
        bim = new BufferedImage(1000, 1000, BufferedImage.TYPE_INT_ARGB);
        gridWorkspace = new BufferedImage(1000, 1000, BufferedImage.TYPE_INT_ARGB);
        layers = new BufferedImage(1000, 1000, BufferedImage.TYPE_INT_ARGB);
        layerSprite = new BufferedImage(1000, 1000, BufferedImage.TYPE_INT_ARGB);

        setLayout(null);
        t = new Thread(this);
        t.start();
    }

    public void setPointArea(int pttX, int pttY, int pttW, int pttH) {
        this.pttX = pttX;
        this.pttY = pttY;
        this.pttW = pttW;
        this.pttH = pttH;
    }

    public void setDraw(boolean draw) {
        this.draw = draw;
    }

    public void drawGrid() {
        tileW = comp.project.getTileWidth();
        tileH = comp.project.getTileHeight();
        int to1 = WorkSpace.pixelsToTiles(getWidth(), tileW) + 1;
        int to2 = WorkSpace.pixelsToTiles(getHeight(), tileH) + 1;

        Graphics2D g2d = (Graphics2D) gridWorkspace.getGraphics();
        g2d.setBackground(color);
        g2d.clearRect(0, 0, getWidth(), getHeight());
        Font font = new Font("SansSerif", Font.PLAIN, tileH / 4);
        g2d.setFont(font);
        FontRenderContext fontRenderContext = g2d.getFontRenderContext();
        g2d.setColor(Color.BLACK);
        if (comp.MenuViewGrid.isSelected()) {
            for (int i = 0; i < to1; i++) {
                g2d.drawLine(i * tileW, 0, i * tileW, getHeight());
            }
            for (int i = 0; i < to2; i++) {
                g2d.drawLine(0, i * tileH, getWidth(), i * tileH);
            }
        }
        if (comp.MenuViewTilePosition.isSelected()) {
            for (int i = 0; i < to1; i++) {
                for (int j = 0; j < to2; j++) {
                    String coords = "(" + (i + pttX) + "," + (j + pttY) + ")";
                    Rectangle2D textSize = font.getStringBounds(coords, fontRenderContext);
                    int x = i * tileW + (int) ((tileW - textSize.getWidth()) / 2);
                    int y = j * tileH + (int) ((tileH + textSize.getHeight()) / 2);
                    g2d.drawString(coords, x, y);
                }
            }
        }
        drawLayer();
    }

    public void drawLayer() {
        Graphics2D g2d = (Graphics2D) layers.getGraphics();
        g2d.setBackground(color);
        g2d.clearRect(0, 0, getWidth(), getHeight());
        LayerContainer lc = comp.layerContainer;
        for (int i = lc.getLayers().size() - 1; i >= 0; i--) {
            Layer lm = (Layer) lc.getLayers().get(i);
            if (lm.isShow()) {
                lm.draw(g2d, pttX, pttY, Math.min(pttW+1, comp.project.getMapWidth()), Math.min(pttH+1, comp.project.getMapHeight()), tileW, tileH);
            }
        }
        drawSprite();
    }

    public void drawLayer(int tx, int ty) {
        Graphics2D g2d = (Graphics2D) layers.getGraphics();
        g2d.setBackground(color);
        g2d.setColor(color);
        int xx = tx - WorkSpace.pixelsToTiles(this.getX(), tileW);
        int yy = ty - WorkSpace.pixelsToTiles(this.getY(), tileH);
        g2d.clearRect(xx * tileW, yy * tileH, tileW, tileH);
        LayerContainer lc = comp.layerContainer;
        for (int i = lc.getLayers().size() - 1; i >= 0; i--) {
            Layer lm = (Layer) lc.getLayers().get(i);
            if (lm.isShow()) {
                lm.drawPosition(g2d, tx, ty, xx, yy, tileW, tileH);
            }
        }
        drawSprite();
    }

    public void drawSprite() {
        if (comp.MenuViewSprite.isSelected()) {
            Graphics2D g2d = (Graphics2D) layerSprite.getGraphics();
            g2d.setBackground(color);
            g2d.clearRect(0, 0, getWidth(), getHeight());

            LayerContainer lc = comp.layerContainer;
            ArrayList<ObjectSprite> al = comp.osContainer.getSprites();
            for (int i = 0; i < al.size(); i++) {
                ObjectSprite os = al.get(i);
                if (os.getPosition() != null) {
                    OSAttribute osa = os.getAttribute(os.getDrawOnLayer());
                    if (osa != null) {
                        BufferedImage bi = (BufferedImage) osa.getAttrib().getImages().get(0);
                        int posSX = os.getPosition().x - (pttX * tileW);
                        int posSY = os.getPosition().y - (pttY * tileH);
                        g2d.drawImage(bi, posSX, posSY, null);
                    }
                }
            }
        }
        drawAll();
    }

    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g3d = (Graphics2D) bim.getGraphics();
        g3d.setBackground(color);
        g3d.clearRect(0, 0, 1000, 1000);
        g3d.drawImage(layers, null, 0, 0);

        if (comp.MenuViewSprite.isSelected()) {
            g3d.drawImage(layerSprite, null, 0, 0);
        }
        if (comp.MenuViewGrid.isSelected() || comp.MenuViewTilePosition.isSelected()) {
            g3d.drawImage(gridWorkspace, null, 0, 0);
        }

        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(bim, 0, 0, null);
    }

    public void drawAll() {
        paintComponent(this.getGraphics());
        this.comp.ScrollPaneWorkspaceRender.repaint();
    }

    @Override
    public void run() {
        while (true) {
            try {
                if (draw) {
                    drawAll();
                    draw = false;
                }
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
            }
        }
    }

    public void interupt() {
        t.interrupt();
    }
}